home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / threads / ThreadsInit.c < prev    next >
C/C++ Source or Header  |  1992-01-16  |  20KB  |  821 lines

  1. /* begincopyright
  2.   Copyright (c) 1988 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA 94304
  14.   endcopyright */
  15.  
  16. /*
  17.  * ThreadsInit.c
  18.  *
  19.  * Demers, February 15, 1991 4:02:11 pm PST
  20.  * Weiser, October 1989
  21.  * Boehm, October 2, 1991 12:17:02 pm PDT
  22.  *
  23.  * Xerox Runtime threads package initialization.
  24.  */
  25.  
  26. #include "xr/BasicTypes.h"
  27. #include "xr/Errno.h"
  28. #include "xr/Threads.h"
  29. #include "xr/ThreadsBackdoor.h"
  30. #include "xr/ThreadsPrivate.h"
  31. #include "xr/ThreadsSharedMem.h"
  32. #include "xr/ThreadsMsgPrivate.h"
  33. #include "xr/ThreadsStatsPrivate.h"
  34. #include "xr/ThreadsTermination.h"
  35. #include "xr/ThreadsSignalsPrivate.h"
  36.  
  37. #include <sys/types.h>
  38. #include <sys/file.h>
  39. #include <sys/stat.h>
  40. #include <sys/socket.h>
  41. #include <sys/fcntl.h>
  42. #include <string.h>
  43. #include <sgtty.h>
  44. #include <sys/resource.h>
  45.  
  46. #define MAX_HEAP_BYTES        (128*1024*1024)
  47.  
  48. #define XR_WARMSTACKSPACE        (XR_MIN_THREAD_STACK_BYTES/4)
  49. #define XR_OFLOHANDLERSTACKSPACE    (XR_MIN_THREAD_STACK_BYTES/4)
  50.  
  51. /*
  52.  * Utility for calling initialization procs that must succeed ...
  53.  */
  54.  
  55. #define TRY(callresult, dopanic) XR_FailWithMsg((callresult), (dopanic))
  56.  
  57. static void
  58. XR_FailWithMsg(msg, pflag)
  59.     char *msg;
  60.     bool pflag;
  61. {
  62.     if( msg ) {
  63.         if( pflag ) XR_Panic(msg);
  64.         XR_ConsoleMsg("%s\n", msg);
  65.         _exit(1);
  66.     }
  67. }
  68.  
  69.  
  70. /*
  71.  * Well-known file descriptors
  72.  */
  73.  
  74. int XR_stdInFD = 0;
  75. int XR_stdOutFD = 1;
  76.  
  77. int XR_socket0FD = -1;
  78. int XR_socket1FD = -1;
  79. int XR_freeFD = -1;
  80.  
  81.  
  82. static void
  83. XR_MoveDescriptor(from, to)
  84.     int from;
  85.     int to;
  86. {
  87.     if( from == to ) return;
  88.     if( (dup2(from, to) < 0) || (close(from) < 0) )
  89.         XR_Panic("MoveDescriptor 0");
  90. }
  91.  
  92. int
  93. XR_InstallDescriptor(d)
  94.     int d;
  95. {
  96.     int ans;
  97.  
  98.     ans = XR_freeFD;
  99.     XR_MoveDescriptor( d, ans );
  100.     XR_freeFD -= 1;
  101.     return ans;
  102. }
  103.  
  104.  
  105. int
  106. XR_SetUnixDescriptorBlocking(fd, blocking)
  107.     int fd;
  108.     bool blocking;
  109. {
  110.     int cFlags;
  111.  
  112.     if( fd < 0 ) return (-EINVAL);
  113.     if( (cFlags = fcntl(fd, F_GETFL, NIL)) < 0 ) return (-EIO);
  114.     if( blocking )
  115.     cFlags &= (~FNDELAY);
  116.     else
  117.     cFlags |= FNDELAY;
  118.     if( fcntl(fd, F_SETFL, cFlags) < 0 ) return (-EIO);
  119.     return 0;
  120. }
  121.  
  122.  
  123.  
  124. #define   XR_FDTABLEMAX   256
  125.  
  126. static int
  127. XR_SetDTableSizeMax()
  128. {
  129.     struct rlimit rl;
  130.     int  dt_max;
  131.  
  132.     if( getrlimit(RLIMIT_NOFILE, &rl) == 0) {
  133.         dt_max = rl.rlim_max;
  134.         if( dt_max > XR_FDTABLEMAX )
  135.             dt_max = XR_FDTABLEMAX;
  136.         rl.rlim_cur = dt_max;
  137.         (void)setrlimit(RLIMIT_NOFILE, &rl);
  138.     }
  139.     return getdtablesize();
  140. }
  141.  
  142.  
  143. static void
  144. XR_CleanUpDescriptors()
  145. {
  146.     (void)XR_SetUnixDescriptorBlocking(XR_stdInFD, TRUE);
  147.     (void)XR_SetUnixDescriptorBlocking(XR_stdOutFD, TRUE);
  148. }
  149.  
  150. static void (*XR_cleanUpDescriptors)() = XR_CleanUpDescriptors;
  151.  
  152. static void
  153. XR_InitDescriptors()
  154. {
  155.     int i;
  156.     int nFD, segFD;
  157.     int sv[2];
  158.     int ans;
  159.  
  160.     if(XR_SetDTableSizeMax() < 0)
  161.         XR_Panic("InitDescriptors 1");
  162.  
  163.     XR_freeFD = getdtablesize() - 1;
  164.  
  165.     XR_stdInFD = XR_InstallDescriptor(XR_stdInFD);
  166.     (void)XR_SetUnixDescriptorBlocking(XR_stdInFD, FALSE);
  167.  
  168.     XR_stdOutFD = XR_InstallDescriptor(XR_stdOutFD);
  169.     (void)XR_SetUnixDescriptorBlocking(XR_stdOutFD, FALSE);
  170.  
  171.  
  172.     ans = socketpair(
  173.         /* af */ AF_UNIX,
  174.         /* type */ SOCK_DGRAM,
  175.         /* protocol */ 0,
  176.         /* sv */ &sv[0]
  177.     );
  178.     if( ans < 0 ) XR_Panic("InitDescriptors 2");
  179.     if( sv[0] > sv[1] ) { int temp = sv[0]; sv[1] = sv[0]; sv[1] = temp; }
  180.     XR_socket1FD = XR_InstallDescriptor(sv[1]);
  181.     XR_socket0FD = XR_InstallDescriptor(sv[0]);
  182.     (void)XR_RegisterTerminationCleanupProc(&XR_cleanUpDescriptors, NIL);
  183. }
  184.  
  185.  
  186. /*
  187.  * Data structure initialization
  188.  */
  189.  
  190. void
  191. XR_InitThread (t)
  192.     XR_Thread t;
  193. {
  194.     t->t_errno = 0;
  195.     t->t_errnoLock = 0;
  196.  
  197.     t->t_vpeToReschedOnMonitorExit = NIL;
  198.     t->t_mlNeeded = NIL;
  199.  
  200.     t->t_index = t - &(XR_sysArea->sa_threadPool[0]);
  201.     t->t_timeoutIndex = 0;
  202.     t->t_gen = 1;
  203.  
  204.     t->t_sStat = XR_SSTAT_NONE;
  205.     t->t_pri = XR_PRI_IDLE;
  206.     t->t_when = XR_END_OF_TIME;
  207.  
  208.     t->t_next = NIL;
  209.     t->t_tq = NIL;
  210.  
  211.     t->t_schedCtlInfo = 0;
  212.     t->t_disabled = 0;
  213.  
  214.     t->t_wNext = NIL;
  215.     t->t_wq = NIL;
  216.  
  217.     XR_InitializeCondition(&(t->t_timerCV), XR_WAIT_FOREVER);
  218.     XR_EnableAborts( &(t->t_timerCV) );
  219.  
  220.     t->t_swStat = XR_SWSTAT_NONE;
  221.  
  222.     XR_InitHandlerData(&(t->t_handlerData), t);
  223.  
  224.     XR_InitSeg( &(t->t_stack.stack_seg), NIL );    /* updated later */
  225.     t->t_stack.stack_handlerInitial = NIL;
  226.     t->t_stack.stack_clientInitial = NIL;
  227.     t->t_stack.stack_warmLimit = NIL;
  228.  
  229.     t->t_abortable = FALSE;
  230.     t->t_abortRequest = FALSE;
  231.  
  232.     t->t_jumpSP = NIL;
  233.     t->t_jumpProc = NIL;
  234.     t->t_jumpArg = NIL;
  235.  
  236.     XR_InitializeMonitor(&(t->t_ml));
  237.     t->t_startProc = NIL;
  238.     t->t_result = NIL;
  239.     t->t_jStat = XR_JSTAT_NONE;
  240.     XR_InitializeCondition(&(t->t_jCVc), XR_WAIT_FOREVER);
  241.     XR_InitializeCondition(&(t->t_jCVp), XR_WAIT_FOREVER);
  242.  
  243.     t->t_dbMsg = XR_DB_MSG_NONE;
  244.     t->t_dbFreeze = FALSE;
  245.     t->t_dbFrozen = FALSE;
  246.  
  247.     t->t_dynEnv = NIL;
  248.     (void)bzero( t->t_perThreadData, (sizeof t->t_perThreadData) );
  249. }
  250.  
  251.  
  252. void
  253. XR_InitHandlerData (handler, next)
  254.     XR_HandlerData handler;
  255.     XR_Thread next;
  256. {
  257.     handler->hd_proc = NIL;
  258.     handler->hd_clientData = NIL;
  259.     handler->hd_which = 0;
  260.     handler->hd_arg = 0;
  261.     handler->hd_result = 0;
  262. }
  263.  
  264.  
  265. void
  266. XR_InitIOPOrder (iopo)
  267.     XR_IOPOrder iopo;
  268. {
  269.     iopo->iopo_next = NIL;
  270.     iopo->iopo_done = FALSE;
  271.     XR_InitializeCondition( &(iopo->iopo_cv), XR_WAIT_FOREVER );
  272.     iopo->iopo_proc = NIL;
  273.     iopo->iopo_cancel = NIL;
  274. }
  275.  
  276. void
  277. XR_InitVPOrder (vpo)
  278.     XR_VPOrder vpo;
  279. {
  280.     vpo->vpo_proc = NIL;
  281.     vpo->vpo_stop = FALSE;
  282. }
  283.  
  284.  
  285. void
  286. XR_InitVPE (vpe)
  287.     XR_VPE vpe;
  288. {
  289.     vpe->vpe_index = vpe - &(XR_sysArea->sa_vpe[0]);
  290.     vpe->vpe_pid = 0;
  291.     vpe->vpe_pri = XR_PRI_IDLE;
  292.     vpe->vpe_doSwitch = FALSE;
  293.     vpe->vpe_ticksSinceBoot = 0;
  294.     vpe->vpe_orderNum = 0;
  295.     vpe->vpe_dbStat = XR_DBSTAT_RUN;
  296.     vpe->vpe_rusage = NIL;
  297. }
  298.  
  299.  
  300. void
  301. XR_InitIOPE (iope)
  302.     XR_IOPE iope;
  303. {
  304.     int i;
  305.  
  306.     iope->iope_index = iope - &(XR_sysArea->sa_iope[0]);
  307.     iope->iope_pid = 0;
  308.     iope->iope_kind = 0;    /* to be set later! */
  309.     iope->iope_flags = 0;
  310.     iope->iope_workerProc = NIL;
  311.     XR_InitVPOrder( &(iope->iope_vpOrderBuf) );
  312.     XR_InitializeMonitor( &(iope->iope_orderLock) );
  313.     XR_InitializeCondition( &(iope->iope_orderAccepted), XR_WAIT_FOREVER );
  314.     iope->iope_order = NIL;
  315.     for( i = 0; i < XR_MAX_IOPE_CLIENT_DATA; i++ ) {
  316.         iope->iope_clientData[i] = 0;
  317.     }
  318. }
  319.  
  320.  
  321.  
  322. XR_MesaProc
  323. XR_MakeMesaProc (proc, x)
  324.     XR_UntypedProc proc;
  325.     XR_Pointer x;
  326. {
  327.     XR_MesaProc mp;
  328.  
  329.     if( XR_currThread != NIL ) {
  330.         mp = (XR_MesaProc)
  331.                 (XR_malloc( sizeof(struct XR_MesaProcRep) ));
  332.     } else {
  333.         mp = (XR_MesaProc)
  334.                 (XR_AllocSharedSysMem( sizeof(struct XR_MesaProcRep) ));
  335.     }
  336.     mp->mp_proc = proc;
  337.     mp->mp_x = x;
  338.     return( mp );
  339. }
  340.  
  341.  
  342. static void
  343. XR_CreateThreadsStacksArea()
  344. {
  345.     unsigned totalBytes = 0;
  346.     unsigned totalThreads = 0;
  347.     int i;
  348.  
  349.     for( i = 0; i < XR_maxThreadStackGroups; i++ ) {
  350.         unsigned nThreads, nBytes;
  351.         nBytes = XR_RoundToPage(
  352.             XR_threadStackGroups[i].tsg_stackBytes, XR_ROUND_UP );
  353.         XR_threadStackGroups[i].tsg_stackBytes = nBytes;
  354.         nThreads = XR_threadStackGroups[i].tsg_numThreads;
  355.         totalThreads += nThreads;
  356.         totalBytes += nThreads * nBytes;
  357.     }
  358.     TRY(XR_InitSharedStackMem(totalThreads, totalBytes), TRUE);
  359. }
  360.  
  361.  
  362.  
  363.  
  364. static void
  365. XR_AssignThreadStackForGroup (t, group)
  366.     XR_Thread t;
  367.     int group;
  368. {
  369.     struct XR_SegRep tSeg;
  370.     unsigned bytes;
  371.     XR_Pointer stack_address;
  372.  
  373.     bytes = XR_threadStackGroups[group].tsg_stackBytes;
  374.     if( bytes != XR_RoundToPage(bytes, XR_ROUND_UP) )
  375.         XR_Panic("AssignThreadStackForGroup 0: stacksize not page-multiple");
  376.     stack_address = XR_AllocSharedStackMem(t->t_index, bytes);
  377.     if( stack_address == NIL )
  378.         XR_Panic("AssignThreadStackForGroup 1: out of memory");
  379.     XR_InitSeg2( &(t->t_stack.stack_seg), stack_address, bytes );
  380.     t->t_stack.stack_handlerInitial =
  381.             (stack_address + bytes);
  382.     t->t_stack.stack_clientInitial =
  383.             (stack_address + bytes - XR_OFLOHANDLERSTACKSPACE);
  384.     t->t_stack.stack_warmLimit = (stack_address + XR_WARMSTACKSPACE);
  385. }
  386.  
  387.  
  388. /*
  389.  * Idle procs.
  390.  * These don't start until all VPs have been installed.
  391.  */
  392.  
  393. static XR_Pointer
  394. XR_Idle (mp)
  395.     XR_MesaProc mp;
  396. {
  397.  
  398.     XR_SetPriority(XR_PRI_IDLE);
  399.     XR_DisableSignals();
  400.     for(;;) {
  401.         if( !(XR_vpe->vpe_doSwitch) ) XR_WaitForSignal();
  402.         XR_EnableSignals();
  403.         XR_Yield();
  404.         XR_DisableSignals();
  405.     }
  406. #ifdef UNDEFINED
  407.     for(;;) {
  408.         if( XR_vpe->vpe_doSwitch ) {
  409.         XR_EnableSignals();
  410.         XR_Yield();
  411.         XR_DisableSignals();
  412.     } else {
  413.         XR_WaitForSignal();
  414.     }
  415.     }
  416. #endif
  417. }
  418.  
  419. /*
  420.  * A high priority thread that will "bounce" attempts to schedule it.
  421.  * This is used if we want to ensure that the currently running thread
  422.  * will make progress, even if the UNIX scheduler suspends us once we return
  423.  * from ReschedSigHandler.  By making this thread runnable instead,
  424.  * another vp can pick up the interesting one.  If we don't get suspended,
  425.  * then we immediately switch back to an interesting thread.
  426.  * We try to ensure that scheduling this thread will invoke the
  427.  * sigcleanup system call, thus giving UNIX a chance to suspend us
  428.  * when we expect it.
  429.  */
  430. XR_Thread XR_trampolineThread = NIL;
  431. struct XR_CVRep XR_trampoline_cv = {0};
  432. bool XR_trampolineOnWQ= FALSE;      /* Ready to have state set to WAIT_CV */
  433. int XR_trampolineCount = 0;     /* How often did I bounce of the trampoline? */
  434.  
  435. static XR_Pointer
  436. XR_Trampoline (mp)
  437.     XR_MesaProc mp;
  438. {
  439.     /* XR_SetPriority doesn't let us do this */
  440.     XR_currThread -> t_pri = XR_PRI_SYS_EXCLUSIVE;
  441.     XR_trampolineThread = XR_currThread;
  442.     XR_InitializeCondition(&XR_trampoline_cv, XR_WAIT_FOREVER);
  443.     
  444.     for (;;) {
  445.         while (XR_trampolineOnWQ) {
  446.              /* Signal handler hasn't seen me yet.  Shouldn't happen. */
  447.          kill(XR_vpe -> vpe_pid, XR_SIG_RESCHED);
  448.         }
  449.         XR_AcquireGSL(&(XR_trampoline_cv.cv_gsl));
  450.         XR_trampolineCount++;
  451.         XR_DisableSignals();
  452.         kill(XR_vpe -> vpe_pid, XR_SIG_RESCHED);
  453.         /* Make myself ready for signal handler to make me not runnable */
  454.             XR_trampolineOnWQ = TRUE;
  455.             XR_AddTlWQ(&(XR_trampoline_cv.cv_wq), XR_currThread);
  456.         XR_EnableSignals();
  457.         /* The pending Resched signal is delivered here */
  458.     }
  459. }
  460.  
  461. static struct XR_MesaProcRep XR_idleMesaProcRep = { XR_Idle, 0 };
  462.  
  463. static XR_Pointer
  464. XR_Idle0(mp)
  465.     XR_MesaProc mp;
  466. {
  467.     extern unsigned XR_StartMainXR();
  468.     struct XR_CTRep child1;
  469.     struct XR_CTRep child2;
  470.  
  471.     XR_SetPriority(XR_PRI_USER_NORMAL);
  472.     if (XR_sysArea->sa_numVP > 1) {
  473.         XR_Fork( &(child1), XR_MakeMesaProc(XR_Trampoline, 0) );
  474.     }
  475.     XR_Fork( &(child2), XR_MakeMesaProc(XR_StartMainXR, 0) );
  476.     return (*(XR_idleMesaProcRep.mp_proc))(&XR_idleMesaProcRep);
  477. }
  478.  
  479. static struct XR_MesaProcRep XR_idle0MesaProcRep = { XR_Idle0, 0 };
  480.  
  481.  
  482. void
  483. XR_InitIdleThread(i)
  484.     int i;
  485. {
  486.     XR_Thread t;
  487.     XR_MesaProc mp;
  488.  
  489.     t = XR_RemHdTQ(&(XR_sysArea->sa_freeTQ[0]));
  490.     if( t == NIL ) XR_Panic("InitIdleThread");
  491.     t->t_pri = XR_PRI_IDLE;
  492.     t->t_swStat = XR_SWSTAT_THREAD;
  493.     t->t_jumpProc = XR_ForkJumpProc;
  494.     mp = ((i == 0) ? &XR_idle0MesaProcRep : &XR_idleMesaProcRep);
  495.     t->t_jumpArg = ((unsigned)(mp));
  496.     t->t_jumpSP = t->t_stack.stack_clientInitial;
  497.     t->t_sStat = XR_SSTAT_READY;
  498.     XR_AddTlTQ( &(XR_sysArea->sa_readyTQ[XR_PRI_IDLE]), t );
  499. }
  500.  
  501.  
  502. static void
  503. XR_SetupSharedDataSeg()
  504. {
  505.     struct XR_SegRep seg;
  506.  
  507.     XR_GetSharedDataSeg( &(seg) );
  508.     if( seg.seg_bytes > 0 ) {
  509.         TRY(XR_ShareMemInitial(seg.seg_addr), TRUE);
  510.     }
  511. }
  512.  
  513.  
  514. static struct XR_SARep XR_sysAreaRep;
  515.  
  516. XR_SA XR_sysArea = NIL;
  517.  
  518. void
  519. XR_InitSA ()
  520. /*
  521.     Allocate, map and initialize system area.
  522.     Called by first processor, so XR_sysArea is shared by all.
  523. */
  524. {
  525.     int i, j;
  526.     XR_Thread t;
  527.     XR_TQ thread_free_queue;
  528.     unsigned heap_bytes;
  529.  
  530.     XR_sysArea = &XR_sysAreaRep;
  531.  
  532.     XR_GetSharedDataSeg( &(XR_sysArea->sa_sharedDataSeg) );
  533.  
  534.     XR_InitPSL(&(XR_sysArea->sa_metaLock));
  535. #   if XR_DEBUG_METALOCK
  536.         XR_sysArea->sa_metaLockerPID = (XR_Pointer)(0);
  537.         XR_sysArea->sa_metaLockerName = (XR_Pointer)(NIL);
  538.         XR_sysArea->sa_metaLockerThread = (XR_Pointer)(NIL);
  539. #   endif /* XR_DEBUG_METALOCK */
  540.  
  541.     XR_InitializeCondition(&(XR_sysArea->sa_threadAvail), XR_MsecToTicks(1000));
  542.     XR_InitTQ(&(XR_sysArea->sa_preFreeTQ));
  543.     for( i = 0; i < XR_maxThreadStackGroups; i++ ) {
  544.         XR_InitTQ(&(XR_sysArea->sa_freeTQ[i]));
  545.     }
  546.     for( i = 0; i <= XR_PRI_LAST; i++ ) {
  547.         XR_InitTQ(&(XR_sysArea->sa_readyTQ[i]));
  548.     }
  549.  
  550.     XR_InitializeMonitor(&(XR_sysArea->sa_mlSchedCtl));
  551.     XR_sysArea->sa_schedCtlMaster = NIL;
  552.     XR_InitializeCondition( &(XR_sysArea->sa_cvSchedCtl), XR_WAIT_FOREVER );
  553.  
  554.     XR_SetBootTime();
  555.     XR_sysArea->sa_doTimeouts = FALSE;
  556.     XR_sysArea->sa_nTimeouts = 0;
  557.  
  558.     XR_sysArea->sa_ttinRecvd = 0;
  559.  
  560.     XR_sysArea->sa_dbpid = 0;        /* updated later */
  561.     XR_sysArea->sa_dbData = NIL;
  562.     XR_sysArea->sa_dbStat = XR_DBSTAT_RUN;
  563.     XR_sysArea->sa_examinee = NIL;
  564.  
  565.     XR_sysArea->sa_numVP = 0;        /* updated later */
  566.     XR_sysArea->sa_numIOP = 0;        /* updated later */
  567.     XR_InitializeMonitor(&(XR_sysArea->sa_mlIOP));
  568.  
  569.     XR_sysArea->sa_vpOrderNum = 0;
  570.     XR_sysArea->sa_vpOrder = NIL;
  571.     XR_InitSG( &(XR_sysArea->sa_vpOrderSem), (1+XR_VP_ORDER_SEM_LAST) );
  572.     XR_VSem( &(XR_sysArea->sa_vpOrderSem), XR_VP_ORDER_SEM_LOCK, 1);
  573.     XR_sysArea->sa_vpOrderMaster = NIL;
  574.  
  575.     XR_sysArea->sa_heapNum = 0;
  576.  
  577.     /* XR_sysArea->sa_heapSeg initialized below, after XR_AssignThreadStack */
  578.  
  579. #   if XR_STATS
  580.     XR_sysArea->sa_stats =
  581.         (int *)(XR_AllocSharedSysMem((1+XR_STATS_LAST)*(sizeof(int))));
  582.     for( i = 0; i <= XR_STATS_LAST; i++ ) {
  583.         XR_sysArea->sa_stats[i] = 0;
  584.     }
  585. #   else
  586.     XR_sysArea->sa_stats = NIL;
  587. #   endif
  588.  
  589.     XR_InitializeMonitor( &(XR_sysArea->sa_mlRUsage) );
  590.  
  591.     XR_InitPSL(&(XR_sysArea->sa_terminating));
  592.     XR_sysArea->sa_terminationStatus = 0; /* irrelevant */
  593.     XR_sysArea->sa_panicMsg = NIL;
  594.  
  595.     for( i = 0; i <= XR_maxThreads; i++ ) {
  596.     XR_sysArea->sa_timeouts[i] = NIL;
  597.     }
  598.  
  599.     for( i = 0; i < XR_maxVPs; i++ )
  600.         XR_InitVPE( &(XR_sysArea->sa_vpe[i]) );
  601.  
  602.     for( i = 0; i < XR_maxIOPs; i++ )
  603.     XR_InitIOPE( &(XR_sysArea->sa_iope[i]) );
  604.  
  605.     { XR_Pointer heapAddr = XR_InitSharedHeapMem( MAX_HEAP_BYTES );
  606.         if( heapAddr == NIL ) { XR_Panic("InitSA: can't initialize heap"); }
  607.         XR_InitSeg2( &(XR_sysArea->sa_heapSeg), heapAddr, 0 );
  608.     }
  609.     XR_sysArea->sa_heapLimit = XR_ComputeAddress(
  610.             XR_sysArea->sa_heapSeg.seg_addr,
  611.             MAX_HEAP_BYTES, XR_ROUND_DOWN );
  612.  
  613.     XR_CreateThreadsStacksArea();
  614.     t = &(XR_sysArea->sa_threadPool[0]);
  615.     for( i = 0; i < XR_maxThreadStackGroups; i++ ) {
  616.         thread_free_queue = &(XR_sysArea->sa_freeTQ[i]);
  617.         for( j = 0; j < XR_threadStackGroups[i].tsg_numThreads; j++ ) {
  618.             XR_InitThread( t );
  619.             XR_AssignThreadStackForGroup(t, i);
  620.             t->t_fq = thread_free_queue;
  621.             if( (i == 0) && (j < XR_maxVPs) ) {
  622.                 /* put (maxVPs) threads on idle free queue to get started */
  623.                 XR_AddTlTQ( thread_free_queue, t );
  624.             } else {
  625.                 XR_AddTlTQ( &(XR_sysArea->sa_preFreeTQ), t );
  626.             }
  627.             t++;
  628.         } 
  629.     }
  630.  
  631.     for( i = 0; i < XR_MAX_SA_CLIENT_DATA; i++ )
  632.         XR_sysArea->sa_clientData[i] = NIL;
  633.  
  634.     for( i = 0; i < XR_maxVPs; i++ )
  635.         XR_InitIdleThread(i);
  636.  
  637. }
  638.  
  639.  
  640. /*
  641.  * wait for installation
  642.  */
  643.  
  644.  
  645. static void
  646. XR_AwaitIOPInstallation(i)
  647.     int i;
  648. {
  649.     XR_IOPE iope = &(XR_sysArea->sa_iope[i]);
  650.     while( iope->iope_pid == 0 ) XR_SpinStep(100000);
  651. }
  652.  
  653. static void
  654. XR_AwaitVPInstallation(i)
  655.     int i;
  656. {
  657.     XR_VPE vpe = &(XR_sysArea->sa_vpe[i]);
  658.     while( vpe->vpe_pid == 0 ) XR_SpinStep(100000);
  659. }
  660.  
  661.  
  662.  
  663. /*
  664.  * Configuration for IOProcessors
  665.  */
  666.  
  667. typedef struct XR_IOPTableEntryRep {
  668.     int (*iopte_config)(/* int nAvail, int default */);
  669.     void (*iopte_setup)(/* int base, int cnt */);
  670.     void (*iopte_run)();
  671.     int iopte_numIOP;    /* default value, if necessary */
  672. } * XR_IOPTableEntry;
  673.  
  674.  
  675. extern int XR_ConfigSlaveIOP();
  676. extern void XR_SetupSlaveIOP();
  677. extern void XR_RunSlaveIOP();
  678.  
  679. extern int XR_ConfigUIOIOP();
  680. extern void XR_SetupUIOIOP();
  681. extern void XR_RunUIOIOP();
  682.  
  683. static struct XR_IOPTableEntryRep XR_iopt[] = {
  684.     {
  685.     XR_ConfigSlaveIOP,
  686.     XR_SetupSlaveIOP,
  687.     XR_RunSlaveIOP,
  688.     0
  689.     },
  690.     {
  691.     XR_ConfigUIOIOP,
  692.     XR_SetupUIOIOP,
  693.     XR_RunUIOIOP,
  694.     0
  695.     }
  696. };
  697.  
  698.  
  699.  
  700. void
  701. XR_InitIOPs(maxIOPs)
  702.     int maxIOPs;
  703. {
  704.     int iopNum, numIOP, nextNumIOP, cnt, i, child;
  705.     XR_IOPTableEntry iopte, ioptLim;
  706.  
  707.     numIOP = 0;
  708.     ioptLim = ((XR_IOPTableEntry)(((unsigned)(XR_iopt)) + (sizeof XR_iopt)));
  709.     for( iopte = XR_iopt; iopte < ioptLim; iopte++ ) {
  710.     if( iopte->iopte_config != NIL ) {
  711.         cnt = (*iopte->iopte_config)
  712.         ( maxIOPs-numIOP, iopte->iopte_numIOP );
  713.     } else {
  714.         cnt = iopte->iopte_numIOP;
  715.     }
  716.     if( cnt == 0 ) continue;
  717.     nextNumIOP = numIOP + cnt;
  718.         if( nextNumIOP > maxIOPs ) XR_Panic("InitIOPs 1");
  719.         iopte->iopte_numIOP = cnt;
  720.         if( iopte->iopte_setup != NIL ) {
  721.             (*(iopte->iopte_setup))(numIOP, cnt);
  722.         }
  723.         numIOP = nextNumIOP;
  724.     }
  725.  
  726.     iopNum = 0;
  727.     for( iopte = XR_iopt; iopte < ioptLim; iopte++ ) {
  728.         for( i = 0; i < iopte->iopte_numIOP; i++ ) {
  729.             int child = fork();
  730.         if( child < 0 ) {
  731.         XR_Panic("InitIOPs 0");
  732.         }
  733.         if( child == 0 ) {
  734.             int pid = getpid();
  735.             XR_iope = &(XR_sysArea->sa_iope[iopNum]);
  736.             XR_InstallSigHandlers();
  737.             XR_iope->iope_pid = pid;
  738.             XR_iope->iope_kind = (unsigned)(iopte->iopte_run);
  739.             (*(iopte->iopte_run))();
  740.             /*NOTREACHED*/
  741.             XR_Panic("InitIOPs 2");
  742.         }
  743.         iopNum++;
  744.         }
  745.     }
  746.  
  747.     for( i = 0; i < numIOP; i++ ) {
  748.     XR_AwaitIOPInstallation(i);
  749.     XR_sysArea->sa_numIOP += 1;
  750.     }
  751.  
  752. }
  753.  
  754.  
  755. static void
  756. XR_StartVP(i, n)
  757.     int i;    /* vp index */
  758.     int n;    /* number of vps */
  759. {
  760.     XR_VPE vpe = &(XR_sysArea->sa_vpe[i]);
  761.     int j;
  762.  
  763.     XR_vpe = vpe;
  764.     XR_InstallSigHandlers();
  765.     XR_sysArea->sa_numVP += 1;
  766.     vpe->vpe_pid = getpid();
  767.     for( j = 0; j < n; j++ ) XR_AwaitVPInstallation(j);
  768.     XR_LockMeta("StartVP");
  769.     XR_DispatchNewThread(NIL, XR_SWSTAT_THREAD);
  770.     /*NOTREACHED*/
  771. }
  772.  
  773.  
  774. void
  775. XR_InitAndRunVPs (numVP)
  776.     int numVP;
  777. {
  778.     int i;
  779.  
  780.     for( i = (numVP-1); i > 0; i-- ) {
  781.     int child = fork();
  782.     if( child < 0 ) XR_Panic("InitAndRunVPs: can't fork");
  783.         if( child == 0 ) {
  784.             XR_StartVP(i, numVP);
  785.             /*NOTREACHED*/
  786.         } else {
  787.         XR_AwaitVPInstallation(i);
  788.         }
  789.     }
  790.     XR_StartVP(0, numVP);
  791.     /*NOTREACHED*/
  792. }
  793.  
  794.  
  795. void
  796. XR_InitAndRunInner()
  797. {
  798.     extern void XR_SetupCommandLoop();
  799.     extern void XR_SetupGC();
  800.     extern void XR_SetupDynamicLoader();
  801.     extern void XR_SetupPackage();
  802.  
  803.     TRY(XR_InitSharedMem(), FALSE);
  804.     XR_SetupSharedDataSeg();
  805.     TRY(XR_InitSharedSysMem(XR_maxSysMem), TRUE);
  806.     XR_InitDescriptors();
  807.     XR_InitSA();
  808.     XR_SetupCommandLoop();
  809.     XR_SetupGC();
  810.     XR_SetupDynamicLoader();
  811.     XR_SetupPackage();
  812.     XR_InitIOPs(XR_maxIOPs);
  813.     XR_InitAndRunVPs(XR_maxVPs);
  814.     /*NOTREACHED*/
  815. }
  816.  
  817.  
  818.  
  819.  
  820.  
  821.